﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using WarningForeverClone.src.sprites;
using Microsoft.Xna.Framework.Content;
using WarningForeverClone.src.weapons;
using WarningForeverClone.src.util;

namespace WarningForeverClone.src.ships
{
    public class Ship
    {
        Vector2 position;
        Sprite sprite;

        List<Weapon> shotsFired;

        const float speed = 8f;

        //Limits how long before the next shot can be fired
        const int maxLaserRechargeTime = 16;
        int laserRechargeTime = 0;

        string selectedWeapon;

        public const int maxHealth = 100;
        public float health = maxHealth;

        public static Color[] bits;

        public Ship()
        {
            sprite = new Sprite("Textures/ship0");
            shotsFired = new List<Weapon>();
            selectedWeapon = "greenLaser";
        }
        public Ship(Vector2 startingPosition)
             : this()
        {
            position = startingPosition;
        }

        public void LoadContent(ContentManager content)
        {
            sprite.LoadContent(content);
            bits = new Color[sprite.Texture.Width * sprite.Texture.Height];
            sprite.Texture.GetData<Color>(bits);
        }
        public void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(sprite.Texture, position, Color.White);
        }

        public void MoveForward()
        {
            position.Y -= speed;
        }
        public void MoveBackward()
        {
            position.Y += speed;
        }
        public void MoveLeft()
        {
            position.X -= speed;
        }
        public void MoveRight()
        {
            position.X += speed;
        }

        public void FireSelectedWeapon()
        {
            if (selectedWeapon == "greenLaser")
            {
                FireGreenLaser();
            }
            else if (selectedWeapon == "blueLaser")
            {
                FireBlueLaser();
            }
            else if (selectedWeapon == "redLaser")
            {
                FireRedLaser();
            }
        }
        public void ChangeWeapon(string newWeapon)
        {
            selectedWeapon = newWeapon;
        }
        private void FireGreenLaser()
        {
            if (laserRechargeTime >= maxLaserRechargeTime)
            {
                laserRechargeTime = 0;

                GreenLaser l = greenLaserPool.Get();
                l.Reset();
                l.Position = position + new Vector2((Width / 2) - (l.Dimensions.X / 2) - 20, -Height + 30);
                shotsFired.Add(l);

                GreenLaser l2 = greenLaserPool.Get();
                l2.Reset();
                l2.Position = position + new Vector2((Width / 2) - (l.Dimensions.X / 2) + 20, -Height + 30);
                shotsFired.Add(l2);
            }
        }
        private void FireBlueLaser()
        {
            if (laserRechargeTime >= maxLaserRechargeTime)
            {
                const double rotation = Math.PI / 3;
                laserRechargeTime = 0;

                BlueLaser l = blueLaserPool.Get();
                l.Reset();
                l.Position = position + new Vector2((Width / 2), -Height + 30);
                l.Velocity = new Vector2((float)(speed * Math.Cos(rotation)), (float)(-speed * Math.Sin(rotation)));
                l.Rotation = -(rotation + Math.PI/2);
                shotsFired.Add(l);

                BlueLaser l2 = blueLaserPool.Get();
                l2.Reset();
                l2.Position = position + new Vector2((Width / 2), -Height + 30);
                l2.Velocity = new Vector2((float)(-speed * Math.Cos(rotation)), (float)(-speed * Math.Sin(rotation)));
                l2.Rotation = rotation + Math.PI / 2;
                shotsFired.Add(l2);
            }
        }
        private void FireRedLaser()
        {
            if (laserRechargeTime >= maxLaserRechargeTime)
            {
                laserRechargeTime = 0;
                Vector2 velocity = new Vector2(0, -2);

                RedLaser l = redLaserPool.Get();
                l.Reset();
                l.Velocity = velocity;
                l.Position = position + new Vector2((Width / 2) - (l.Dimensions.X / 2) - 45, -Height + 10);
                shotsFired.Add(l);

                RedLaser l2 = redLaserPool.Get();
                l2.Reset();
                l2.Velocity = velocity;
                l2.Position = position + new Vector2((Width / 2) - (l.Dimensions.X / 2) - 15, -Height + 10);
                shotsFired.Add(l2);

                RedLaser l3 = redLaserPool.Get();
                l3.Reset();
                l3.Velocity = velocity;
                l3.Position = position + new Vector2((Width / 2) - (l.Dimensions.X / 2) +15, -Height + 10);
                shotsFired.Add(l3);

                RedLaser l4 = redLaserPool.Get();
                l4.Reset();
                l4.Velocity = velocity;
                l4.Position = position + new Vector2((Width / 2) - (l.Dimensions.X / 2) + 45, -Height + 10);
                shotsFired.Add(l4);
            }
        }

        /// <summary>
        /// Keep the player inside the specified bounds
        /// </summary>
        /// <param name="left"></param>
        /// <param name="top"></param>
        /// <param name="right"></param>
        /// <param name="bottom"></param>
        public void KeepOnScreen(int left, int top, int right, int bottom)
        {
            if (position.X < left)
                position.X = left;
            if (position.X + Width > right)
                position.X = right - Width;

            if (position.Y < top)
                position.Y = top;
            if (position.Y + Height > bottom)
                position.Y = bottom - Height;
        }
        public void UpdateShots(Boss boss)
        {
            boss.CheckCollisions(shotsFired);

            //count up to when the next shot can be fired
            if (laserRechargeTime < maxLaserRechargeTime)
                laserRechargeTime++;

            for (int x = 0; x < shotsFired.Count; x++)
            {
                Weapon w = (Weapon)shotsFired[x];

                //remove weapons offscreen and ones that aren't alive
                if (!w.Alive || !w.IsOnScreen())
                {
                    DeleteShot(w);
                    x--;
                    continue;
                }

                w.Update();
            }
        }

        /// <summary>
        /// Remove this instance of a weapon from the world
        /// </summary>
        /// <param name="w"></param>
        private void DeleteShot(Weapon w)
        {
            if (w is GreenLaser)
                greenLaserPool.Free((GreenLaser)w);
            else if (w is BlueLaser)
                blueLaserPool.Free((BlueLaser)w);
            else if (w is RedLaser)
                redLaserPool.Free((RedLaser)w);

            shotsFired.Remove(w);
        }

        public int Width
        {
            get { return sprite.Texture.Width; }
        }
        public int Height
        {
            get { return sprite.Texture.Height; }
        }

        public Vector2 Position
        {
            get { return position; }
        }

        /// <summary>
        /// Weapons that are currently in the world
        /// </summary>
        public List<Weapon> ShotsFired
        {
            get { return shotsFired; }
        }

        public string SelectedWeapon
        {
            get { return selectedWeapon; }
        }

        //weapon pools to remove overhead of creating and destroying objects so quickly
        private static Pool<GreenLaser> greenLaserPool;
        private static Pool<BlueLaser> blueLaserPool;
        private static Pool<RedLaser> redLaserPool;
        static Ship()
        {
            greenLaserPool = new Pool<GreenLaser>(20);
            blueLaserPool = new Pool<BlueLaser>(40);
            redLaserPool = new Pool<RedLaser>(80);
        }

    }
}
